/**
 * 
 */
package com.app.framework.orm.session;

import com.app.framework.exception.ORMException;
import com.app.framework.orm.StorableModel;
import com.app.model.Condition;

/**
 * @author lisong
 * @version 2013-4-17 下午5:31:15
 */
public class Query {

	public enum Operator {
		EQ,
		GT,
		LT,
		GE,
		LE
	}
	public enum Order {
		ASC {
			@Override
			public String toString() {
				return "ASC";
			}
		},
		DESC{
			@Override
			public String toString() {
				return "DESC";
			}
		}
	}
	private Class<? extends StorableModel> classType=null;
	
	private Condition condition=null;
	
	/**
	 * <b>Query的构造函数</b>
	 * @param classType 需要查找的对象实体的类名
	 */
	public Query(Class<? extends StorableModel> classType){
		this.classType = classType;
		initialCondition();
	}
	
	public Class<? extends StorableModel> getClassType() {
		return classType;
	}

	public Condition getCondition() {
		return condition;
	}
	
	private void initialCondition() {
		condition=new Condition();
        condition.setFilterAttr("");
        condition.setFilterType("");
        condition.setFilterValue("");
        condition.setFilterOperator("");
        condition.setOrderAttr("");
        condition.setOrderDir("");
        condition.setLimitOffset(0);
        condition.setLimitRange(100);
	}
	
	/**
	 * convert the operator to string
	 * @param operator
	 * @return
	 */
	private String operatorToString(Operator operator){
		switch(operator){
		case EQ:
			return "=";
		case GT:
			return ">";
		case LT:
			return "<";
		case GE:
			return ">=";
		case LE:
			return "<=";
		default:
			return "=";
		}
	}
	
	/**
	 * <b>设置查询的过滤条件</b>
	 * @param filterAttr 设置过滤的属性值
	 * @param operator 设置过滤的比较符
	 * @param filterValue 设置过滤的比较值,注意：如果参数小于 10的-3次方 或大于等于 10的7次方，则参数会默认使用计算机科学记数法 表示，此时查询会出现异常
	 * @return Query对象自身
	 */
	public Query setFilter(String filterAttr,Operator operator, float filterValue){
        condition.setFilterAttr(filterAttr);
        condition.setFilterType("float");
        condition.setFilterValue(Float.toString(filterValue));
        condition.setFilterOperator(operatorToString(operator));
        return this;
	}
	
	public Query setFilter(String filterAttr,Operator operator, long filterValue){
        condition.setFilterAttr(filterAttr);
        condition.setFilterType("bigint");
        condition.setFilterValue(String.valueOf(filterValue));
        condition.setFilterOperator(operatorToString(operator));
        return this;
	}

	/**
	 * <b>设置查询的过滤条件</b>
	 * @param filterAttr 设置过滤的属性值
	 * @param operator 设置过滤的比较符
	 * @param filterValue 设置过滤的比较值
	 * @return Query对象自身
	 */
	public Query setFilter(String filterAttr,Operator operator, int filterValue){
        condition.setFilterAttr(filterAttr);
        condition.setFilterType("int");
        condition.setFilterValue(String.valueOf(filterValue));
        condition.setFilterOperator(operatorToString(operator));
        return this;
	}
	
	/**
	 * <b>设置查询的过滤条件</b>
	 * @param filterAttr 设置过滤的属性值
	 * @param operator 设置过滤的比较符
	 * @param filterValue 设置过滤的比较值
	 * @return Query对象自身
	 */
	public Query setFilter(String filterAttr,Operator operator, String filterValue){
        condition.setFilterAttr(filterAttr);
        condition.setFilterType("string");
        condition.setFilterValue(filterValue);
        condition.setFilterOperator(operatorToString(operator));
        return this;
	}
	
	/**
	 * <b>限制返回的对象实体个数和偏移量</b>
	 * @param limitOffset 设置的偏移量 最小为0
	 * @param limitRange 返回值个数的上限。上限最大值为100，若传入参数大于100，则截断为100
	 * @return Query对象自身
	 * @throws ORMException
	 */
	public Query setLimit(int limitOffset,int limitRange) throws ORMException{
		if (limitOffset<0) {
			throw new ORMException("limit at least be 0");
		}
		if (limitRange>100) {
			limitRange=100;
		}
		condition.setLimitOffset(limitOffset);
		condition.setLimitRange(limitRange);
		
		return this;
	}
	
	/**
	 * <b>设置查询的排序条件</b>
	 * @param orderAttr 设置需要排序的属性值
	 * @param orderDir 设置需要排序的方式（升序或者降序）
	 * @return
	 */
	public Query setOrder(String orderAttr,Order orderDir){
        condition.setOrderAttr(orderAttr);
    	condition.setOrderDir(orderDir.toString());
        return this;
	}
	public static void main(String[] args) {
		new Query(StorableModel.class).setFilter("", Operator.EQ, System.currentTimeMillis());
	}
}

